// Shader Global Variable
// (c) jimon game studio

#include "CShaderGlobalVariable_OpenGL.h"

#ifdef JE_RENDER_OPENGL

#include "CRender_OpenGL.h"

namespace je
{
	namespace video
	{
		//! Constructor
		CShaderGlobalVariable_OpenGL::CShaderGlobalVariable_OpenGL(const jeStringc & Name,IRender * Render)
			:CurrentName(Name),CurrentRender(Render),EnableCache(true),EnableIgnoreVoidShaderVariables(false)
		{
		}

		//! Destructor
		CShaderGlobalVariable_OpenGL::~CShaderGlobalVariable_OpenGL()
		{
			for(u32 i=0;i<ShaderVariablesList.GetSize();i++)
				ShaderVariablesList[i]->Drop();
			ShaderVariablesList.Clear();

			static_cast<CRender_OpenGL*>(CurrentRender)->RemoveGlobalShaderVariable(this);
		}

		//! Get Shader Variable Name
		const jeStringc & CShaderGlobalVariable_OpenGL::GetName()
		{
			return CurrentName;
		}

		//! Set Matrix
		void CShaderGlobalVariable_OpenGL::SetMatrix(const jeMatrix4f & Matrix)
		{
			for(u32 i=0;i<ShaderVariablesList.GetSize();i++)
				ShaderVariablesList[i]->SetMatrix(Matrix);
		}

		//! Set Matrix 3x3 (set up 3x3 part of 4x4 matrix)
		void CShaderGlobalVariable_OpenGL::SetMatrix3x3(const jeMatrix4f & Matrix)
		{
			for(u32 i=0;i<ShaderVariablesList.GetSize();i++)
				ShaderVariablesList[i]->SetMatrix3x3(Matrix);
		}

		//! Set s32
		void CShaderGlobalVariable_OpenGL::Sets32(const s32 * Data,s32 Size)
		{
			for(u32 i=0;i<ShaderVariablesList.GetSize();i++)
				ShaderVariablesList[i]->Sets32(Data,Size);
		}

		//! Set f32
		void CShaderGlobalVariable_OpenGL::Setf32(const f32 * Data,s32 Size)
		{
			for(u32 i=0;i<ShaderVariablesList.GetSize();i++)
				ShaderVariablesList[i]->Setf32(Data,Size);
		}

		//! Set Vector Array
		void CShaderGlobalVariable_OpenGL::SetVector(const jeVector3df * Vector,s32 Size)
		{
			for(u32 i=0;i<ShaderVariablesList.GetSize();i++)
				ShaderVariablesList[i]->SetVector(Vector,Size);
		}

		//! Set Vector
		void CShaderGlobalVariable_OpenGL::SetVector(const jeVector3df & Vector)
		{
			for(u32 i=0;i<ShaderVariablesList.GetSize();i++)
				ShaderVariablesList[i]->SetVector(Vector);
		}

		//! Set Vector
		void CShaderGlobalVariable_OpenGL::SetVector(const jeVector3di & Vector)
		{
			for(u32 i=0;i<ShaderVariablesList.GetSize();i++)
				ShaderVariablesList[i]->SetVector(Vector);
		}

		//! Set Vector
		void CShaderGlobalVariable_OpenGL::SetVector(const jeVector2df & Vector)
		{
			for(u32 i=0;i<ShaderVariablesList.GetSize();i++)
				ShaderVariablesList[i]->SetVector(Vector);
		}

		//! Set Vector
		void CShaderGlobalVariable_OpenGL::SetVector(const jeVector2di & Vector)
		{
			for(u32 i=0;i<ShaderVariablesList.GetSize();i++)
				ShaderVariablesList[i]->SetVector(Vector);
		}
		
		//! Set Cached Setup
		void CShaderGlobalVariable_OpenGL::SetCachedSetup(u1 Enable)
		{
			EnableCache = Enable;
			for(u32 i=0;i<ShaderVariablesList.GetSize();i++)
				ShaderVariablesList[i]->SetCachedSetup(Enable);
		}

		//! Is Cached Setup
		u1 CShaderGlobalVariable_OpenGL::IsCachedSetup()
		{
			return EnableCache;
		}

		//! Is Exist In Shader
		u1 CShaderGlobalVariable_OpenGL::IsExistInShader()
		{
			for(u32 i=0;i<ShaderVariablesList.GetSize();i++)
				if(ShaderVariablesList[i]->IsExistInShader())
					return true;
			return false;
		}
		
		//! Remove Void Shader Variables
		void CShaderGlobalVariable_OpenGL::RemoveVoidShaderVariables()
		{
			for(u32 i=0;i<ShaderVariablesList.GetSize();i++)
				if(!ShaderVariablesList[i]->IsExistInShader())
				{
					ShaderVariablesList[i]->Drop();
					ShaderVariablesList.EraseElement(i--);
				}
		}

		//! Set Ignore Void Shader Variables
		void CShaderGlobalVariable_OpenGL::SetIgnoreVoidShaderVariables(u1 Enable)
		{
			EnableIgnoreVoidShaderVariables = Enable;
		}

		//! Is Ignore Void Shader Variables
		u1 CShaderGlobalVariable_OpenGL::IsIgnoreVoidShaderVariables()
		{
			return EnableIgnoreVoidShaderVariables;
		}

		//! Get Variables List
		IShaderGlobalVariable::ShadersVariablesListType * CShaderGlobalVariable_OpenGL::GetVariablesList()
		{
			return &ShaderVariablesList;
		}

		//! Register Variable
		void CShaderGlobalVariable_OpenGL::RegisterVariable(IShaderVariable * Variable)
		{
			if(EnableIgnoreVoidShaderVariables && (!Variable->IsExistInShader()))
				return;

			ShaderVariablesList.InsertElement(Variable);
			Variable->Grab();
			Variable->SetCachedSetup(EnableCache);
		}

		//! Erase Variable
		void CShaderGlobalVariable_OpenGL::EraseVariable(IShaderVariable * Variable)
		{
			u32 Result = 0;
			if(ShaderVariablesList.LinearSearch(Variable,Result))
			{
				ShaderVariablesList.EraseElement(Result);
				Variable->Drop();
			}
		}
	}
}

#endif
